package org.mushroomdb.index;

import java.util.Iterator;

import org.apache.log4j.Logger;
import org.mushroomdb.catalog.Column;
import org.mushroomdb.catalog.Register;
import org.mushroomdb.catalog.Types;
import org.mushroomdb.filemanagement.Page;
import org.mushroomdb.index.hash.ExtensibleHash;

public class HashBasedIndex implements Index {
	
	private String name;
	private Column column;
	private ExtensibleHash hash;
	private Logger logger;
	
	/**
	 * Constructor.
	 * @param column
	 * @param page
	 */
	public HashBasedIndex(String name, Column column, Page page) {
		this.logger = Logger.getLogger(this.getClass());
		this.name = name;
		this.column = column;
		this.hash = new ExtensibleHash(page, Types.getJavaClass(column.getType()));
	}

	/**
	 * @see org.mushroomdb.index.Index#getName()
	 */
	public String getName() {
		return this.name;
	}
	
	/**
	 * @see org.mushroomdb.index.Index#getColumn()
	 */
	public Column getColumn() {
		return this.column;
	}

	/**
	 * @see org.mushroomdb.index.Index#insert(com.mdlm.rdbms.catalog.Register)
	 */
	public void insert(Register register, long pageNumber) {
		int index = register.getColumnIndex(this.column);
		if (index > 0) {
			Object key = register.getValue(index);
			//try {
				this.hash.addKey(key,pageNumber);
//			} catch (IOException e) {
//				throw new RDBMSRuntimeException(e);
//			}
			this.logger.warn("Index insertion: key " + key + " at page " + pageNumber); //$NON-NLS-1$ //$NON-NLS-2$
		} else {
			this.logger.warn("Column " + this.column + " does not belong to this index. Ignoring insertion."); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * @see org.mushroomdb.index.Index#update(com.mdlm.rdbms.catalog.Register)
	 */
	public void update(Register register, int columnIndex, Object value) {
		// TODO: Si se updatea el campo indexado hay que borra y agregar.
		// si la columna modificada es la del indice, hay que actualizar
		if(register.getColumnIndex(this.column) == columnIndex) {
			long pageNumber = this.hash.removeKey(register.getValue(columnIndex));
			this.hash.addKey(value, pageNumber);
		}
		// this.removeKey(oldKey);
		//this.insert(register,value);
	}

	/**
	 * @see org.mushroomdb.index.Index#delete(com.mdlm.rdbms.catalog.Register)
	 */
	public void delete(Register register) {
		int index = register.getColumnIndex(this.column);
		this.hash.removeKey(register.getValue(index));
	}

	/**
	 * @see org.mushroomdb.index.Index#searchEqualsTo(java.lang.Object)
	 */
	public Iterator searchEqualsTo(Object key) {
		Page dataPage = this.hash.getDataPage(key);
		TablePage tablePage = new TablePage(dataPage,this.getColumn(),key);
		return tablePage.getRegisters();
	}

	/**
	 * @see org.mushroomdb.index.Index#searchLessOrEqualThan(java.lang.Object)
	 */
	public Iterator searchLessOrEqualThan(Object key) {
		// TODO: Que hacemo con este tipo de busqueda???
		return null;
//		Page dataPage = this.hash.getDataPage(key);
//		TablePage tablePage = new TablePage(dataPage,this.getColumn(),key);
//		Iterator iterator = tablePage.getRegisters();
//		
//		node = node.getPreviousNode();
//		while (node != null) {
//			tablePage = new TablePage(node.getPage(key),this.getColumn(),key);
//			iterator = new MultipleIterator(iterator,tablePage.getRegisters());
//			node = node.getNextNode();
//		}
//		
//		return iterator;
	}

	/**
	 * @see org.mushroomdb.index.Index#searchGreatherOrEqualThan(java.lang.Object)
	 */
	public Iterator searchGreatherOrEqualThan(Object key) {
		// TODO: Que hacemo con este tipo de busqueda???
		return null;
//		DataNode node = this.bPlusTree.getNode(key);
//		TablePage tablePage = new TablePage(node.getPage(key),this.getColumn(),key);
//		Iterator iterator = tablePage.getRegisters();
//		
//		node = node.getNextNode();
//		while (node != null) {
//			tablePage = new TablePage(node.getPage(key),this.getColumn(),key);
//			iterator = new MultipleIterator(iterator,tablePage.getRegisters());
//			node = node.getNextNode();
//		}
//		
//		return iterator;
	}
}
